
#import "RNMpaas.h"
#import <React/RCTLog.h>
#import <React/RCTRootView.h>
#import <React/RCTConvert.h>
#import "MpaassWebViewController.h"
#import "MBProgressHUD.h"

@interface RNMpaasViewController : UIViewController

@end

@implementation RNMpaasViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
}

- (void)viewWillAppear:(BOOL)animated{
  [super viewWillAppear:animated];
  if (!self.navigationController.navigationBarHidden) {
    [self.navigationController setNavigationBarHidden:YES animated:YES];
  }
}

@end

@interface RNMpaas ()

@end

@implementation RNMpaas
{
    BOOL hasListeners;
}

RCT_EXPORT_MODULE()

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

- (NSArray<NSString *> *)supportedEvents
{
  return @[@"tinyToRn", @"tinyToRnChannel"];
}

// 在添加第一个监听函数时触发
-(void)startObserving {
    hasListeners = YES;
    // Set up any upstream listeners or background tasks as necessary
    RNMpaasWrapper.shareInstance.mpaas = self;
}

// Will be called when this module's last listener is removed, or on dealloc.
-(void)stopObserving {
    hasListeners = NO;
    // Remove upstream listeners, stop unnecessary background tasks
    RNMpaasWrapper.shareInstance.mpaas = nil;
}

- (void)tinyHandler:(NSDictionary *)data context:(PSDContext *)context callbackid:(NSString *)callbackid
{
    if (hasListeners) { // Only send events if anyone is listening
        [self sendEventWithName:@"tinyToRn" body:@{@"data": data, @"callbackid": callbackid}];
    }
}

- (void)tinyChannelHandler:(NSDictionary *)data context:(PSDContext *)context channelId:(NSString *)channelId
{
    if (hasListeners) { // Only send events if anyone is listening
        [self sendEventWithName:@"tinyToRnChannel" body:@{@"data": data, @"channelId": channelId}];
    }
}

RCT_EXPORT_METHOD(callbackTiny:(NSString *)callbackid result:(NSDictionary *)result)
{
    PSDJsApiResponseCallbackBlock callback = (PSDJsApiResponseCallbackBlock)(RNMpaasWrapper.shareInstance.callbacks[callbackid]);
    if (callback) {
        //暂时先注释掉，不移除了，可以支持多次回调，实现类似监听事件
        //似乎不支持多次回调，第一次回调能收到，后面的都收不到，所以还是移除了吧，需要实现监听效果，可以再发起tinyToRn调用，附带上callbackid
        [RNMpaasWrapper.shareInstance.callbacks removeObjectForKey:callbackid];
        callback(result);
    }
}

RCT_EXPORT_METHOD(callbackTinyChannel:(NSString *)callbackid result:(NSDictionary *)result)
{
    if (self.sendEvent) {
        self.sendEvent(callbackid, result);
    }
}

RCT_EXPORT_METHOD(LaunchMini:(NSString *)appID params:(NSDictionary *)params hideTitle:(BOOL)hideTitle onExit:(RCTResponseSenderBlock)onExit) {
    RCTLogInfo(@"%@", appID);
    NSString *queryvalue = [self handleQuery:params[@"query"] ?: params];
    NSMutableDictionary * dic = [params mutableCopy];
    [dic removeObjectForKey:@"query"];
    [dic addEntriesFromDictionary:@{@"query": queryvalue}];
    RNMpaasWrapper.shareInstance.hideMPH5NavigationBar = hideTitle; // 是否隐藏原生导航栏
    RNMpaasWrapper.shareInstance.onExit = onExit; // 小程序退出时回调
    [MPNebulaAdapterInterface startTinyAppWithId:appID params:dic];
}
RCT_EXPORT_METHOD(ScanQRLaunchMini:(NSString *)uri params:(NSDictionary *)params onExit:(RCTResponseSenderBlock)onExit) {
    NSString *queryvalue = [self handleQuery:params[@"query"] ?: params];
    NSMutableDictionary * dic = [params mutableCopy];
    [dic removeObjectForKey:@"query"];
    [dic addEntriesFromDictionary:@{@"query": queryvalue}];
    RNMpaasWrapper.shareInstance.onExit = onExit; // 小程序退出时回调
    [MPNebulaAdapterInterface startDebugTinyAppWithUrl:uri params:dic];
}

RCT_EXPORT_METHOD(registerID:(NSString *)userId)
{
    RNMpaasWrapper.shareInstance.userId = userId;
}

RCT_EXPORT_METHOD(loginOUt)
{
    RNMpaasWrapper.shareInstance.userId = nil;
}

RCT_EXPORT_METHOD(updateAllApp)
{
    // 全量更新小程序包
    [[MPNebulaAdapterInterface shareInstance] requestAllNebulaApps:^(NSDictionary *data, NSError *error) {
        NSLog(@"全量更新小程序包%@：%@", error ? @"失败" : @"成功", error ?: data);
    }];
}

RCT_EXPORT_METHOD(showLoading:(NSString *)text)
{
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].keyWindow animated:YES];
    hud.label.text = text;
}

RCT_EXPORT_METHOD(hideLoading)
{
    [MBProgressHUD hideHUDForView:[UIApplication sharedApplication].keyWindow animated:YES];
}

RCT_EXPORT_METHOD(startWebView:(NSString *)title url:(NSString *)url userAgent:(NSString *)userAgent options:(NSDictionary *)options)
{
    options = options ?: @{};
    MpaassWebViewController *webViewVc = MpaassWebViewController.new;
    if ([userAgent isKindOfClass:NSString.class]) {
        webViewVc.userAgent = userAgent;
    }
    webViewVc.title = title;
    webViewVc.source = @{@"url": url ?: @""};
    webViewVc.originNavigationBarHidden = RNMpaasWrapper.shareInstance.hideMPH5NavigationBar;
    webViewVc.waterString = options[@"waterStr"];
    webViewVc.flagAddWater = [webViewVc.waterString isKindOfClass:NSString.class];
    UINavigationController *rootVc = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    [rootVc pushViewController:webViewVc animated:YES];
}

RCT_EXPORT_METHOD(bringRnToBack:(NSDictionary *)options)
{
    options = options ?: @{};
    [self bringViewControllerToBackWithClass:NSClassFromString(@"NewOfficeBaseViewController")];
}

RCT_EXPORT_METHOD(bringRnToFront:(NSDictionary *)options)
{
    options = options ?: @{};
    [self bringViewControllerToFrontWithClass:NSClassFromString(@"NewOfficeBaseViewController")];
}

// 新建原生页面嵌套 rn 模块
// 该方案废弃。。有很多问题需要解决：比如传参 props 支持函数参数，解决起来很麻烦、比如 rn 子页面跳转另外的 rn 子页面
RCT_EXPORT_METHOD(newRnView:(NSString *)moduleName options:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback)
{
    options = options ?: @{};
    NSMutableDictionary *mProps = NSMutableDictionary.new;
    [mProps addEntriesFromDictionary:options[@"props"] ?: options];
    NSArray *funcProps = options[@"funcProps"] ?: @[];
    [funcProps enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSString *key = (NSString *)obj;
        void (^func)(id) = ^(id response) {
            callback(@[key, response]);
        };
        [mProps setObject:func forKey:key];
    }];
    UINavigationController *rootVc = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    NSMutableArray *mArr = [rootVc.childViewControllers mutableCopy];
    __block UIViewController *rnVc = nil;
    [mArr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:NSClassFromString(@"NewOfficeBaseViewController")]) {
            rnVc = obj;
        }
    }];
    RCTRootView *rootView = (RCTRootView *)rnVc.view;
    if ([rootView isKindOfClass:RCTRootView.class]) {
        RCTRootView *rnView = [[RCTRootView alloc] initWithBridge:rootView.bridge
                                                         moduleName:moduleName
                                                  initialProperties:mProps];

        rnView.backgroundColor = UIColor.whiteColor;
        RNMpaasViewController *vc = RNMpaasViewController.new;
        vc.view = rnView;
        [rootVc pushViewController:vc animated:YES];
    }
}
// 退出原生页面嵌套的 rn 模块
RCT_EXPORT_METHOD(exitRnView:(NSDictionary *)options) {
    options = options ?: @{};
    UINavigationController *rootVc = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    if ([rootVc.topViewController isKindOfClass:RNMpaasViewController.class]) {
        BOOL animated = YES;
        if (options[@"animated"] != nil) {
            animated = [options[@"animated"] boolValue];
        }
        [rootVc popViewControllerAnimated:animated];
    }
}

//调整 ViewController 位置 by index
- (void)bringViewControllerToIndex:(NSUInteger)to fromIndex:(NSUInteger)from {
    UINavigationController *rootVc = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    NSMutableArray *mArr = [rootVc.childViewControllers mutableCopy];
    if (from < mArr.count && to < mArr.count && from != to) {
        NSObject *fromObj = mArr[from];
        [mArr removeObjectAtIndex:from];
        [mArr insertObject:fromObj atIndex:to];
        [rootVc setViewControllers:mArr animated:YES];
    }
}

//置顶 ViewController by class
- (void)bringViewControllerToFrontWithClass:(Class)class {
    UINavigationController *rootVc = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    NSMutableArray *mArr = [rootVc.childViewControllers mutableCopy];
    __block NSInteger index = mArr.count - 1;
    [mArr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:class]) {
            index = idx;
        }
    }];
    if (index < mArr.count - 1) {
        [self bringViewControllerToIndex:mArr.count - 1 fromIndex:index];
        rootVc.interactivePopGestureRecognizer.enabled = NO;
    }
}

//置底 ViewController by class
- (void)bringViewControllerToBackWithClass:(Class)class {
    UINavigationController *rootVc = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    NSMutableArray *mArr = [rootVc.childViewControllers mutableCopy];
    __block NSInteger index = mArr.count - 1;
    [mArr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:class]) {
            index = idx;
        }
    }];
    if (index > 0) {
        [self bringViewControllerToIndex:0 fromIndex:index];
        rootVc.interactivePopGestureRecognizer.enabled = YES;
    }
}

//字符串编码
- (NSString *) encodString: (NSString *)string {
    string = [NSString stringWithFormat:@"%@", string];
    NSString *encdeString = [string stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:@"?!@#$^&%*+,:;='\"`<>()[]{}/\\| "] invertedSet]];
    return  encdeString;
}
//转换成小程序参数
- (NSString *) handleQuery: (NSDictionary *) params {
    NSMutableString *queryvalue = NSMutableString.new;
    [params enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        NSString *value = [self encodString:obj];
        [queryvalue appendFormat:@"%@=%@&", key, value];
    }];
    return queryvalue;
}
@end

